package ltd.dujiabao.dex.autoconfigure;

import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

import org.quartz.Scheduler;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.listener.RabbitListenerEndpointRegistry;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import ltd.dujiabao.dex.core.emitter.EmitterFactoryHolder;
import ltd.dujiabao.dex.jdk.exe.JdkEmitterFactory;
import ltd.dujiabao.dex.quartz.exe.QuartzEmitterFactory;
import ltd.dujiabao.dex.quartz.exe.QuartzJob;
import ltd.dujiabao.dex.rabbitmq.exe.RabbitDelayJobInitializer;
import ltd.dujiabao.dex.rabbitmq.exe.RabbitEmitterFactory;

/**
 * @author DuJiabao
 * @date 2024/3/18 19:46
 */

@ConditionalOnProperty(value = "ltd.dujiabao.delay-executor.enable", matchIfMissing = true)
@Configuration
@EnableConfigurationProperties(DelayExecutorProperties.class)
public class DelayExecutorAutoConfiguration {

    @Bean
    public EmitterFactoryHolder emitterFactoryHolder() {
        return new EmitterFactoryHolder();
    }

    @ConditionalOnClass(JdkEmitterFactory.class)
    @Configuration
    @ConditionalOnProperty("ltd.dujiabao.delay-executor.jdk.enable")
    public static class JdkDelayExecutorConfiguration {
        @Bean
        public JdkEmitterFactory jdkEmitterFactory(DelayExecutorProperties properties) {
            ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(properties.getJdk().getCoreThreadSize(),
                    new ThreadFactory() {
                        private final AtomicInteger idGenerator = new AtomicInteger(0);

                        @Override
                        public Thread newThread(Runnable r) {
                            return new Thread(r, properties.getJdk().getThreadName() + idGenerator.getAndIncrement());
                        }
                    });
            return new JdkEmitterFactory(executor);
        }
    }

    @Configuration
    @ConditionalOnProperty("ltd.dujiabao.delay-executor.rabbitmq.enable")
    @ConditionalOnClass({RabbitTemplate.class, RabbitEmitterFactory.class})
    public static class RabbitDelayExecutorConfiguration {
        @Bean
        public RabbitDelayJobInitializer rabbitDelayJobInitializer(RabbitListenerEndpointRegistry rabbitListenerEndpointRegistry,
                                                                   RabbitListenerContainerFactory<?> rabbitListenerContainerFactory) {
            return new RabbitDelayJobInitializer(rabbitListenerEndpointRegistry, rabbitListenerContainerFactory);
        }

        @Bean
        public RabbitEmitterFactory rabbitEmitterFactory(RabbitTemplate rabbitTemplate) {
            return new RabbitEmitterFactory(rabbitTemplate);
        }
    }

    @Configuration
    @ConditionalOnProperty("ltd.dujiabao.delay-executor.quartz.enable")
    @ConditionalOnClass({QuartzEmitterFactory.class, Scheduler.class})
    public static class QuartzDelayExecutorConfiguration {
        @Bean
        public QuartzEmitterFactory quartzEmitterFactory(Scheduler scheduler) {
            return new QuartzEmitterFactory(scheduler);
        }

        @Bean
        public QuartzJob quartzJob() {
            return new QuartzJob();
        }
    }
}
